package com.rcclabs.commonutils.gdata.docs.service.impl;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;

import com.google.gdata.client.docs.DocsService;
import com.google.gdata.data.PlainTextConstruct;
import com.google.gdata.data.docs.DocumentEntry;
import com.google.gdata.data.docs.DocumentListEntry;
import com.google.gdata.data.docs.DocumentListFeed;
import com.google.gdata.data.docs.FolderEntry;
import com.google.gdata.data.docs.PresentationEntry;
import com.google.gdata.data.docs.SpreadsheetEntry;
import com.google.gdata.util.AuthenticationException;
import com.google.gdata.util.ServiceException;
import com.rcclabs.commonutils.gdata.common.Constants;
import com.rcclabs.commonutils.gdata.common.DocumentListType;
import com.rcclabs.commonutils.gdata.common.DocumentType;
import com.rcclabs.commonutils.gdata.docs.service.DocumentListService;
import com.rcclabs.commonutils.gdata.exceptions.DocumentListException;

public class DocumentListServiceImpl implements DocumentListService {

	private DocsService service;

	public DocumentListServiceImpl(String applicationName, String userName,
			String password) throws DocumentListException,
			AuthenticationException {
		if (applicationName == null) {
			throw new DocumentListException(
					"applicationName is required to create an instance for this service");
		}

		service = new DocsService(applicationName);
		service.setUserCredentials(userName, password);
	}

	public DocumentListServiceImpl(String applicationName, String token)
			throws DocumentListException, AuthenticationException {
		if (applicationName == null) {
			throw new DocumentListException(
					"applicationName is required to create an instance for this service");
		}

		service = new DocsService(applicationName);
		service.setAuthSubToken(token);
	}

	@Override
	public DocumentListEntry create(String title, DocumentType type)
			throws DocumentListException, MalformedURLException, IOException,
			ServiceException {
		if (title == null || type == null) {
			throw new DocumentListException("null title or type");
		}

		DocumentListEntry newEntry = null;
		if (type.equals(DocumentType.DOCUMENT)) {
			newEntry = new DocumentEntry();
		} else if (type.equals(DocumentType.PRESENTATION)) {
			newEntry = new PresentationEntry();
		} else if (type.equals(DocumentType.SPREADSHEET)) {
			newEntry = new SpreadsheetEntry();
		} else if (type.equals(DocumentType.FOLDER)) {
			newEntry = new FolderEntry();
		}

		newEntry.setTitle(new PlainTextConstruct(title));
		return service.insert(
				buildUrl(Constants.URL_DEFAULT + Constants.URL_DOCLIST_FEED,
						null), newEntry);
	}

	@Override
	public void trash(String resourceId) throws DocumentListException,
			MalformedURLException, IOException, ServiceException {
		if (resourceId == null) {
			throw new DocumentListException("null resourceId");
		}

		String feedUrl = Constants.URL_DEFAULT + Constants.URL_DOCLIST_FEED
				+ "/" + resourceId + "?delete=false";

		service.delete(buildUrl(feedUrl, null), getDocsListEntry(resourceId)
				.getEtag());
	}

	@Override
	public void delete(String resourceId) throws DocumentListException,
			MalformedURLException, IOException, ServiceException {
		if (resourceId == null) {
			throw new DocumentListException("null resourceId");
		}

		String feedUrl = Constants.URL_DEFAULT + Constants.URL_DOCLIST_FEED
				+ "/" + resourceId + "?delete=true";

		service.delete(buildUrl(feedUrl, null), getDocsListEntry(resourceId)
				.getEtag());
	}

	@Override
	public DocumentListFeed getDocsListFeed(DocumentListType category)
			throws DocumentListException, IOException, ServiceException {
		if (category == null) {
			throw new DocumentListException("null category");
		}

		URL url;

		if (category == DocumentListType.ALL) {
			url = buildUrl(Constants.URL_DEFAULT + Constants.URL_DOCLIST_FEED,
					null);
		} else if (category == DocumentListType.FOLDER) {
			String[] parameters = { Constants.PARAMETER_SHOW_FOLDERS };
			url = buildUrl(Constants.URL_DEFAULT + Constants.URL_DOCLIST_FEED
					+ Constants.URL_CATEGORY_FOLDER, parameters);
		} else if (category == DocumentListType.DOCUMENT) {
			url = buildUrl(Constants.URL_DEFAULT + Constants.URL_DOCLIST_FEED
					+ Constants.URL_CATEGORY_DOCUMENT, null);
		} else if (category == DocumentListType.SPREADSHEET) {
			url = buildUrl(Constants.URL_DEFAULT + Constants.URL_DOCLIST_FEED
					+ Constants.URL_CATEGORY_SPREADSHEET, null);
		} else if (category == DocumentListType.PDF) {
			url = buildUrl(Constants.URL_DEFAULT + Constants.URL_DOCLIST_FEED
					+ Constants.URL_CATEGORY_PDF, null);
		} else if (category == DocumentListType.PRESENTATION) {
			url = buildUrl(Constants.URL_DEFAULT + Constants.URL_DOCLIST_FEED
					+ Constants.URL_CATEGORY_PRESENTATION, null);
		} else if (category == DocumentListType.STARRED) {
			url = buildUrl(Constants.URL_DEFAULT + Constants.URL_DOCLIST_FEED
					+ Constants.URL_CATEGORY_STARRED, null);
		} else if (category == DocumentListType.TRASHED) {
			url = buildUrl(Constants.URL_DEFAULT + Constants.URL_DOCLIST_FEED
					+ Constants.URL_CATEGORY_TRASHED, null);
		} else {
			return null;
		}

		return service.getFeed(url, DocumentListFeed.class);
	}

	@Override
	public DocumentListEntry getDocsListEntry(String resourceId)
			throws DocumentListException, IOException, ServiceException {
		if (resourceId == null) {
			throw new DocumentListException("null resourceId");
		}
		URL url = buildUrl(Constants.URL_DEFAULT + Constants.URL_DOCLIST_FEED
				+ "/" + resourceId, null);

		return service.getEntry(url, DocumentListEntry.class);
	}

	private URL buildUrl(String path, String[] parameters)
			throws MalformedURLException, DocumentListException {
		StringBuffer url = new StringBuffer();
		url.append("https://" + Constants.DEFAULT_HOST + Constants.URL_FEED
				+ path);

		if (parameters != null && parameters.length > 0) {
			url.append("?");
			for (int i = 0; i < parameters.length; i++) {
				url.append(parameters[i]);
				if (i != (parameters.length - 1)) {
					url.append("&");
				}
			}
		}

		return new URL(url.toString());
	}

}
